from pathlib import Path
from typing import Dict, List, Tuple
import logging
import openpyxl
from openpyxl.styles import PatternFill, Font, Alignment

class SubmissionChecker:
    def __init__(self, excel_path: Path, homework_dir: Path, output_dir: Path):
        """
        初始化提交检查器
        :param excel_path: 学生选课名单Excel文件路径
        :param homework_dir: 作业文件夹路径
        :param output_dir: 输出目录路径
        """
        self.excel_path = excel_path
        self.homework_dir = homework_dir
        self.output_dir = output_dir
        self.logger = logging.getLogger('homework_grading')

    def check_submissions(self) -> Tuple[Dict[str, List[str]], List[str]]:
        """
        检查作业提交情况
        :return: (已提交学生列表, 未提交学生列表)
        """
        try:
            # 使用 openpyxl 读取 Excel 文件
            wb = openpyxl.load_workbook(self.excel_path, data_only=True)
            ws = wb.active
            
            # 找到学号列的索引
            header_row = next(ws.rows)
            student_id_col = None
            
            # 打印所有列名用于调试
            self.logger.info("Excel文件中的列名:")
            for idx, cell in enumerate(header_row, 1):
                if cell.value:
                    self.logger.info(f"列 {idx}: {cell.value}")
                    # 检查是否包含"学号"（忽略空格和大小写）
                    if "学号" in str(cell.value).replace(" ", "").lower():
                        student_id_col = idx
                        self.logger.info(f"找到学号列: {cell.value} (列 {idx})")
                        break
            
            if student_id_col is None:
                # 如果没找到学号列，尝试其他可能的列名
                possible_columns = ["学号", "学   号", "student_id", "学号", "学号"]
                for idx, cell in enumerate(header_row, 1):
                    if cell.value:
                        cell_value = str(cell.value).strip()
                        if any(col in cell_value for col in possible_columns):
                            student_id_col = idx
                            self.logger.info(f"通过备选名称找到学号列: {cell.value} (列 {idx})")
                            break
            
            if student_id_col is None:
                raise ValueError("Excel文件中没有找到学号列。请确保文件中包含'学号'列。")

            # 获取所有学生学号
            all_students = []
            for row in ws.iter_rows(min_row=2, min_col=student_id_col, max_col=student_id_col):
                if row[0].value:
                    student_id = str(row[0].value).strip()
                    if student_id:  # 确保学号不为空
                        all_students.append(student_id)
            
            self.logger.info(f"从Excel文件中读取到 {len(all_students)} 个学生学号")

            # 获取所有实验目录
            experiment_dirs = [d for d in self.homework_dir.iterdir() if d.is_dir()]
            self.logger.info(f"找到 {len(experiment_dirs)} 个实验目录")

            # 为每个实验目录添加状态列
            for exp_dir in experiment_dirs:
                exp_name = exp_dir.name
                status_col = ws.max_column + 1
                
                # 添加实验名称作为列标题
                status_header = ws.cell(row=1, column=status_col)
                status_header.value = exp_name
                status_header.font = Font(bold=True)
                status_header.alignment = Alignment(horizontal='center')

                # 获取该实验目录下的所有作业文件
                submitted_files = list(exp_dir.glob("*.doc*"))
                submitted_students = []
                
                # 检查每个文件
                for file in submitted_files:
                    try:
                        # 从文件名中提取学号
                        student_id = file.stem.split('_')[0].split('-')[0].split(' ')[0]
                        if student_id in all_students:
                            submitted_students.append(student_id)
                        else:
                            self.logger.warning(f"文件 {file.name} 的学号 {student_id} 不在学生名单中")
                    except Exception as e:
                        self.logger.error(f"处理文件 {file.name} 时出错: {str(e)}")

                # 更新Excel中的提交状态
                for row in ws.iter_rows(min_row=2):
                    student_id = str(row[student_id_col-1].value).strip()
                    if student_id in all_students:
                        status_cell = ws.cell(row=row[0].row, column=status_col)
                        if student_id in submitted_students:
                            status_cell.value = "已交"
                            status_cell.fill = PatternFill(start_color="92D050", end_color="92D050", fill_type="solid")
                        else:
                            status_cell.value = "未交"
                            status_cell.fill = PatternFill(start_color="FF0000", end_color="FF0000", fill_type="solid")
                        status_cell.alignment = Alignment(horizontal='center')

                self.logger.info(f"已完成实验 {exp_name} 的检查")

            # 保存更新后的Excel文件到输出目录
            output_excel = self.output_dir / f"作业提交情况汇总{self.excel_path.suffix}"
            wb.save(output_excel)
            self.logger.info(f"已更新Excel文件并保存为: {output_excel}")

            # 生成报告
            report = {
                "实验目录": [d.name for d in experiment_dirs],
                "总学生数": len(all_students)
            }

            return report, []

        except Exception as e:
            self.logger.error(f"检查作业提交情况时出错: {str(e)}")
            raise

    def save_report(self, report: Dict[str, List[str]], output_path: Path) -> None:
        """
        保存检查报告
        :param report: 检查报告
        :param output_path: 输出文件路径
        """
        try:
            with open(output_path, 'w', encoding='utf-8') as f:
                f.write("作业提交情况检查报告\n")
                f.write("=" * 50 + "\n\n")
                
                f.write(f"总学生数: {report['总学生数']}\n")
                f.write(f"实验目录数: {len(report['实验目录'])}\n\n")
                
                f.write("实验目录列表:\n")
                f.write("-" * 20 + "\n")
                for exp in report['实验目录']:
                    f.write(f"{exp}\n")
                
            self.logger.info(f"检查报告已保存到: {output_path}")
        except Exception as e:
            self.logger.error(f"保存报告时出错: {str(e)}")
            raise 